package com.example.zselasticsearchsf;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.zselasticsearchsf.config.es.respons.SearchRepDto;
import com.example.zselasticsearchsf.domain.*;
import com.example.zselasticsearchsf.dto.SfwDto;
import lombok.extern.log4j.Log4j;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.*;
//import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
import org.elasticsearch.search.aggregations.bucket.histogram.HistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.range.Range;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
//import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;


import javax.annotation.Resource;
import java.io.*;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarOutputStream;

import static org.elasticsearch.index.query.QueryBuilders.matchQuery;

/**
 * @Author: Steven
 * @Date: 2021/10/21 15:01
 */
//@SpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class ElasticSearchDemo {

//    @Autowired
//    private RestHighLevelClient restHighLevelClient;

    @Autowired
    @Qualifier(value = "restHighLevelClient")
    private RestHighLevelClient client;

    @Resource
    private ActionListener<AcknowledgedResponse> listener;

    public ElasticSearchDemo() throws IOException {
    }

    /**
     * es 新增
     * 新增文档 6.8.3
     */

    public void addDoc(SfwDto sfwDto) {
        // 1.准备需要保存到索引库的Json文档数据

        // 2.将对象转为Json字符串
        String jsonString = JSON.toJSONString(sfwDto);

        // 3.创建请求对象,指定索引库、类型、id(可选)
//        要是es上没有这个索引和mapping会自动新建一个索引按照传的字段类型自动建mapping
        IndexRequest indexRequest = new IndexRequest("sfw_12348", "product", null);

        // 4.调用source方法将请求数据封装到IndexRequest请求对象中
        indexRequest.source(jsonString, XContentType.JSON);

        try {
            // 5.调用方法进行数据通信
            IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
            // 6.解析输出结果
            System.out.println("结果：" + JSON.toJSONString(indexResponse));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * ES 全量查询 6.8.3
     */

    @Test
    public void matchDoc() {
        // 1.构建SearchRequest请求对象,指定索引库
//        SearchRequest searchRequest = new SearchRequest("case_info");
        SearchRequest searchRequest = new SearchRequest("case_info");

        // 2.构建SearchSourceBuilder查询对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 3.构建QueryBuilder对象指定查询方式和查询条件
        QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();

        // 4.将QueryBuilder对象设置到SearchSourceBuilder中
        sourceBuilder.size(200);
        sourceBuilder.from(1);
        sourceBuilder.query(queryBuilder);

        // 5.将SearchSourceBuilder对象封装到请求对象SearchRequest中
        searchRequest.source(sourceBuilder);

        try {
            // 6.调用方法进行数据通信
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            // 7.解析输出结果
            SearchHit[] hits = searchResponse.getHits().getHits();
            for (SearchHit hit : hits) {
                String sourceAsString = hit.getSourceAsString();
                System.out.println("结果： " + sourceAsString);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关键词【高亮查询】6.8.3
     */
    @Test
    public void highLightMatch() {

        String keyword = "杨";
        if (keyword == null) {
//            return CommonResult.failed("关键词不能为空!");
        }
        // 1.构建QueryBuilder对象指定查询方式
        QueryBuilder queryBuilder = matchQuery("realname", keyword);

        // 2.构建SearchRequest请求对象,指定索引库
        SearchRequest searchRequest = new SearchRequest("employee_xd");

        // 3.构建SearchSourceBuilder查询对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 4.将QueryBuilder对象设置到SearchSourceBuilder中
        sourceBuilder.query(queryBuilder);

        // 5构建HighlightBuilder高亮对象
        HighlightBuilder highlightBuilder = new HighlightBuilder();

        // 5.1设置要高亮的字段
        highlightBuilder.field("realname");

        // 5.2设置高亮样式
//        highlightBuilder.preTags("<font color='pink' >");
//        highlightBuilder.postTags("</font>");
//                highlightBuilder.preTags("<span style=\"color:pink\" >");
//        highlightBuilder.postTags("</span>");
        highlightBuilder.preTags("<span style='color:blue;font-weight: 900'>");
        highlightBuilder.postTags("</span>");
        // 6.将高亮对象highlightBuilder设置到sourceBuilder中
        sourceBuilder.highlighter(highlightBuilder);

        // 7.将SearchSourceBuilder查询对象封装到请求对象SearchRequest中
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = null;

        List<Object> list = new ArrayList<>();
        try {
            // 8.调用方法进行数据通信
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            // 9.解析输出结果
            SearchHit[] hits = searchResponse.getHits().getHits();
            for (SearchHit hit : hits) {
                String sourceAsString = hit.getSourceAsString();
                System.out.println("结果：" + sourceAsString);
                // 10.获取高亮结果
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                HighlightField realname = highlightFields.get("realname");
                Text[] fragments = realname.getFragments();
                for (Text fragment : fragments) {
                    System.err.println("高亮结果： " + fragment.toString());
                    System.err.println("userId： " + JSON.parseObject(sourceAsString).get("id"));
                    Map<String, Object> highlightMap = new HashMap<>();
                    highlightMap.put("highlightRealName", fragment.toString());
                    highlightMap.put("realName", JSON.parseObject(sourceAsString).get("realname"));
                    highlightMap.put("userId", JSON.parseObject(sourceAsString).get("id"));
                    list.add(highlightMap);
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
//        return   CommonResult.success(searchResponse);

//        return CommonResult.success(list);
        System.out.println(list);

    }


    /**
     * es7.6.x高级客户揣测试创【建索引】
     */
    @Test
    public void creatIndexTest() throws IOException {
//        1/1、创建索引请求

        CreateIndexRequest request = new CreateIndexRequest("case");
//        1/2、客广端执行请求Indicesclient,请求后获得响应 todo 该处6.8.3为admin包，7.几为client包 待验证6.及
//        CreateIndexResponse createIndexResponse = client.indices().create(request,RequestOptions.DEFAULT);
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);

    }


    /**
     * es7.6.x高级客户揣测试  查询索引
     */
    @Test
    public void getIndexTest() throws IOException {
//        1/1、创建索引请求
        GetIndexRequest getIndexRequest = new GetIndexRequest("kuang_index");
//        1/2、客广端执行请求Indicesclient,请求后获得响应
        boolean exit = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(exit);

    }

    /**
     * es7.6.x 高级客户揣测试  测试删除索引
     */
    @Test
    public void testDeleteIndex() throws IOException {

        DeleteIndexRequest request = new DeleteIndexRequest("sfw");
        AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);

        System.out.println(delete.isAcknowledged());
    }

    /**
     * es7.6.x 高级客户揣测试  新建文档
     */
    @Test
    public void testCreateDocument() throws IOException {
        //创建对象
        SfwDto sfwDto = new SfwDto();
        sfwDto.setCaseTittlDateUtilse("1王某甲申请办理居住权合同公证案");
        sfwDto.setNumber("2223123");
        sfwDto.setCaseUrl("1王某甲申请办理居住权合同公证案");
        sfwDto.setCaseTittlDateUtilse("llll");
        sfwDto.setSubmissionTime("2021-10-09");
        sfwDto.setCaseType("公证业务案例");
        sfwDto.setVisits(111);
        //创建请求
        IndexRequest request = new IndexRequest("kuang");
        //规则   put /kuang_index/_doc/1
        request.id("1");//不设置自动
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //  我们的数据放入请求json将
        request.source(JSON.toJSONString(sfwDto), XContentType.JSON);
//        客户端发送请求,获取响应的结果

        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());//返回这行记录（doc）
        System.out.println(indexResponse.status());
        ;//对应我们命令返回的状态CREATED

    }

    /**
     * es7.6.x高级客户揣测试  获取文档,判断是否存在get /index/doc/1   （1为id）
     *
     * @throws IOException
     */
    @Test
    public void testIsExists() throws IOException {
        GetRequest getRequest = new GetRequest("sfw");
        getRequest = new GetRequest("sfw", "5UNKqHwBcApSgYReaQZE");//指定id
//        getRequest = new GetRequest("sfw", "_doc","5UNKqHwBcApSgYReaQZE");//6.8.3
        //不获取返回的_source 的上下文了
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields(" _none_");
        boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println(exists);

    }


    /**
     * es7.6.x高级客户揣测试  获取文档信息
     *
     * @throws IOException
     */
    @Test
    public void testGetDocument() throws IOException {
        /*GetRequest getRequest = new GetRequest("sfw");
        getRequest = new GetRequest( "sfw","5UNKqHwBcApSgYReaQZE");//指定id*/

        GetRequest getRequest = new GetRequest("sfw", "5UNKqHwBcApSgYReaQZE");
//        GetRequest   getRequest = new GetRequest("sfw", "_doc","5UNKqHwBcApSgYReaQZE");//6.8.3

        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(getResponse.getSourceAsString());//打印文档内容
        System.out.println("===============");

        System.out.println(getResponse);

    }


    /**
     * es7.6.x高级客户揣测试  更新文档信息
     *
     * @throws IOException Elasticsearch exception [type=invalid_type_name_exception, reason=Document mapping type name can't start with '_', found: [_update]
     *                     todo        1、Elasticsearch数据库版本为6.8.3，但是客户端Elasticsearch的依赖版本是7.6.1，
     *                     由于Elasticsearch7以上版本的java api默认type为_doc，但是Elasticsearch6的type不支持_开头导致报错。
     *                     maven 降版本可以
     */

    @Test
    public void testUpdateDocument() throws IOException {
//1.创建请求
        UpdateRequest updateRequest = new UpdateRequest("sfw", "5UNKqHwBcApSgYReaQZE");
//        UpdateRequest   updateRequest = new UpdateRequest("sfw", "_doc","5UNKqHwBcApSgYReaQZE");//6.8.3

        updateRequest.timeout("1s");
        //2.创建对象
        SfwDto sfwDto = new SfwDto();
        sfwDto.setCaseTittlDateUtilse("1王某甲申请办理居住权合同公证案");
        sfwDto.setNumber("123cccccc");
        sfwDto.setCaseUrl("http://www.baidu.com");
        sfwDto.setSubmissionTime("2021-10-09");
        sfwDto.setCaseType("公证业务案例");
        sfwDto.setVisits(111);

        //3.匹配规则 我们的数据放入请求json
        updateRequest.doc(JSON.toJSONString(sfwDto), XContentType.JSON);
        //4.发起亲求返回响应数据
        UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(updateResponse);

    }


    /**
     * es7.6.x高级客户揣测试  特殊的，真的项目一殷都会批量插入数据
     * TODO: 2021/10/23   type=action_request_validation_exception, reason=Validation
     *  Failed: 1: type is missing;2: type is missing;]
     */

    @Test
    public void testBulkRequest() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        ArrayList<SfwDto> sfwDtoArrayList = new ArrayList<>();

        SfwDto sfwDto = new SfwDto();
        sfwDto.setCaseTittlDateUtilse("1王某甲申请办理居住权合同公证案");
        sfwDto.setNumber("123cccccc");
        sfwDto.setCaseUrl("http://www.baidu.com");
        sfwDto.setSubmissionTime("2021-10-09");
        sfwDto.setCaseType("公证业务案例");
        sfwDto.setVisits(111);

        sfwDtoArrayList.add(sfwDto);


        sfwDto.setCaseTittlDateUtilse("1王某甲申请办理居住权合同公证案");
        sfwDto.setNumber("123ccccccXXXX");
        sfwDto.setCaseUrl("http://www.aiqiyi.com");
        sfwDto.setSubmissionTime("2021-10-05");
        sfwDto.setCaseType("公证业务案例222");
        sfwDto.setVisits(131114);
        sfwDtoArrayList.add(sfwDto);


        //批处理请求
        for (int i = 0; i < sfwDtoArrayList.size(); i++) {
            //批量更新和批量删除更换add内地请求即可
            bulkRequest.add(
                    new IndexRequest("swf")
//            new IndexRequest("swf","_doc")//6.8.3
                            .id("" + i + 1) //不设置随机 id
                            .source(JSON.toJSONString(sfwDtoArrayList.get(i)), XContentType.JSON));
        }
        BulkResponse bulkItemResponses = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkItemResponses);
        System.out.println(bulkItemResponses.hasFailures());//是否成功 false 代表成功
    }


    @Test
    public void SearchTest() throws IOException {
        Integer size = 10;

        // 1.构建SearchRequest请求对象,指定索引库
        SearchRequest searchRequest = new SearchRequest("law_info");
        // 2.构建SearchSourceBuilder查询对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3.构建QueryBuilder对象指定查询方式和查询条件
//      searchSourceBuilder.query(matchQuery("context", "建平"));
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchSourceBuilder.size(size);
        searchRequest.source(searchSourceBuilder);

//        searchRequest.scroll(TimeValue.timeValueMinutes(1L));
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(searchResponse);
        String scrollId = searchResponse.getScrollId();
        SearchHits hits = searchResponse.getHits();
        System.out.println(scrollId);
        System.out.println(hits);
    }


    /**
     * 只有 sourceBuilder.query(rangeQueryBuilder);from("2017-11-01").to("2017-11-31",  {"relation":"EQUAL_TO","value":0} 且无名字
     * 加了sourceBuilder.query(QueryBuilders.matchAllQuery()); docCount数目为727，有命中,默认前十条
     *
     * @throws IOException 查询 testAggs2 按月分组查出 时段内最小的值 测试一下
     *                     key:2017-11-01
     *                     docCount:2
     * @Return 得到总数=========2  结果：2017-11-30  验证完毕（前期不对是因为下面是没有指定索引，全文查询的，这里case_index）
     */
    @Test
    public void search_rangeQueryest() throws IOException {
        //1.searchRequest 索引名不加为全文搜索
        SearchRequest searchRequest = new SearchRequest("law_info");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //闭区间查询

        QueryBuilder queryBuilder = QueryBuilders.rangeQuery("publishDate").from("2017-11-01").to("2017-11-31", true);
        //开区间查询
        QueryBuilder qb1 = QueryBuilders.rangeQuery("${fieldName}").from("$ {fieldValue1}", false).to("fieldValue2", false);
        //大于
        QueryBuilder qb2 = QueryBuilders.rangeQuery("${fieldName}").gt("$ {fieldValue1}");
        //大于等于
        QueryBuilder qb3 = QueryBuilders.rangeQuery("${fieldName}").gte("$ {fieldValue1}");
        //小于
        QueryBuilder qb4 = QueryBuilders.rangeQuery("${fieldName}").lt("$ {fieldValue1}");
        //小于等于
        QueryBuilder qb5 = QueryBuilders.rangeQuery("${fieldName}").lte("$ {fieldValue1}");
        sourceBuilder.query(queryBuilder);

        // *******将SearchSourceBuilder查询对象封装到请求对象SearchRequest中,否则全匹配  sourceBuilder没起作用啊
        searchRequest.source(sourceBuilder);
        try {
            // 调用方法进行数据通信
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            // 解析输出结果
            SearchHit[] hits = searchResponse.getHits().getHits();
            Long total = searchResponse.getHits().getTotalHits().value;
            System.out.println("总数=========" + total);
            for (SearchHit hit : hits) {
                String id = hit.getId();
                String sourceAsString = hit.getSourceAsString();
                SearchRepDto searchResult = new SearchRepDto();

//                System.out.println("结果：" + sourceAsString);
                System.out.println("结果：" + JSON.parseObject(sourceAsString).getString("publishDate"));
                //#region 解析高亮结果
//                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
//                HighlightField highlightField = highlightFields.get("searchFiled");
//                Text[] fragments = highlightField.getFragments();
//
//                for (Text fragment : fragments) {
                //searchResult.setHighlightField(JSON.parseObject(sourceAsString).getString("contextTitle"));
                //  #endregion              }
            }
           /* for (SearchHit documentFields : hits) {
                System.out.println(documentFields.getSourceAsMap());
            }*/
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 多种构建搜索条件 对比
     * SearchSourceBuilder sourceBuilder（QueryBuiLders）
     *
     * @throws IOException
     */
    @Test
    public void search_XXTest() throws IOException {
        //1.searchRequest 索引名不加为全文搜索
        SearchRequest searchRequest = new SearchRequest();


        //2、构建搜索条件；我们可以使用QueryBuiLders工具来实现（QueryBuilders.termQuery()//精确，/QueryBuilders.matchAllQuery()//匹配所有）

        //1.1 根据时间范围查询
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishDate").from("2017-11-01").to("2017-11-31", true);

        //1.2高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("keyword");
        highlightBuilder.preTags("<span style='color:blue;font-weight: 900'>");
        highlightBuilder.postTags("</span>");

        //1.3精确查询
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("_id", "cTjtGX0BC9oHjpdrrvpG");

        //1.4全匹配
        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();

        //3
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        sourceBuilder.size(100);//默认查10
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//      sourceBuilder.from() //默认-1

//      sourceBuilder.query(termQueryBuilder);
//      sourceBuilder.query(matchQuery("context", "建平"));
        sourceBuilder.query(rangeQueryBuilder);
//      sourceBuilder.query(QueryBuilders.matchAllQuery());
//      sourceBuilder.highlighter(highlightBuilder);

        // *******将SearchSourceBuilder查询对象封装到请求对象SearchRequest中,否则全匹配  sourceBuilder没起作用啊
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(searchResponse);
        System.out.println(JSON.toJSONString(searchResponse.getHits().getTotalHits()));
        System.out.println("===================================");

        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
            System.out.println(documentFields.getSourceAsMap());
        }

        for (SearchHit hit : searchResponse.getHits()) {
            String id = hit.getId();
            String sourceAsString = hit.getSourceAsString();
            System.out.println("结果：" + JSON.parseObject(sourceAsString).get("publishDate"));
            System.out.println("结果id：" + id);
        }
    }
/**###############################################聚合查询###############################################**/
    /**
     * 常用桶聚合
     * Aggregation查询之---TermsAggregation
     * 按照颜色分组，计算每个颜色卖出的个数
     * 按其他类型分组 时间必须为keyword
     *
     * @throws IOException
     */
    @Test
    public void testAggs() throws IOException {

        //#regionGET语句
        // GET /tvs/_search
        // {
        //     "size": 0,
        //     "query": {"match_all": {}},
        //     "aggs": {
        //       "group_by_color": {
        //         "terms": {
        //             "field": "color"
        //         }
        //     }
        // }
        // }
//        #endregion

        //1 构建请求
        SearchRequest searchRequest = new SearchRequest("law_info_b");

        //请求体
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.size();默认查10
//        searchSourceBuilder.query(matchQuery("context", "建平"));
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_by_color").field("distName");
        searchSourceBuilder.aggregation(termsAggregationBuilder);
        //请求体放入请求头
        searchRequest.source(searchSourceBuilder);

        //2 执行
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        //#region3 获取结果 分组统计
        //   "aggregations" : {
        //       "group_by_color" : {
        //           "doc_count_error_upper_bound" : 0,
        //           "sum_other_doc_count" : 0,
        //            "buckets" : [
        //           {
        //               "key" : "红色",
        //               "doc_count" : 4
        //           },
        //           {
        //               "key" : "绿色",
        //                   "doc_count" : 2
        //           },
        //           {
        //               "key" : "蓝色",
        //                   "doc_count" : 2
        //           }
        // ]
        //#endregion       }
        Aggregations aggregations = searchResponse.getAggregations();
        Terms group_by_color = aggregations.get("group_by_color");
        List<? extends Terms.Bucket> buckets = group_by_color.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            String key = bucket.getKeyAsString();
            System.out.println("key:" + key);
            long docCount = bucket.getDocCount();
            System.out.println("docCount:" + docCount);
            System.out.println("=================================");
        }
        SearchHit[] hits = searchResponse.getHits().getHits();
        System.out.println("命中---" + hits.length);
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println("结果： " + sourceAsString);
        }
        System.out.println("===========================");
        for (SearchHit hit : hits) {

            String sourceAsString = hit.getSourceAsString();
            System.out.println("字段： " + JSON.parseObject(sourceAsString).get("distName"));
        }
    }

    @Test
    public void testAggs1() throws IOException {
        // Histogram聚合命名为: prices
        HistogramAggregationBuilder histogramAggregationBuilder = AggregationBuilders.histogram("prices")
                .field("visits") // 根据price字段值，对数据进行分组
                .interval(100); //  分桶的间隔为100，意思就是price字段值按100间隔分组


        //2.搜索
        //构建请求
        SearchRequest searchRequest = new SearchRequest();
        //请求体
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        // 对比上面的（颜色）分组TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_by_color").field("publishDate");
        searchSourceBuilder.aggregation(histogramAggregationBuilder);
        //请求体放入请求头
        searchRequest.source(searchSourceBuilder);
        //执行
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);


        //3 处理聚合查询结果
        Aggregations aggregations = searchResponse.getAggregations();
        // 根据prices命名查询Histogram聚合结果
        Histogram histogram = aggregations.get("prices");

        // 遍历聚合结果
        for (Histogram.Bucket bucket : histogram.getBuckets()) {
            // 获取桶的Key值
            String key = bucket.getKeyAsString();
            System.out.println("key:" + key);
            // 获取文档总数
            long count = bucket.getDocCount();
            System.out.println("count:" + count);
        }
    }

    /**
     * Date histogram聚合
     * Aggregation查询之---DateHistogram
     * 按时间分组 时间字段为date类型
     */
    @Test
    public void testAggs2() throws IOException {

        //1 构建请求
        SearchRequest searchRequest = new SearchRequest();

        //请求体
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        // DateHistogram聚合命名为: sales_over_time
        DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("sales_over_time")
                .field("publishDate") // 根据date字段值，对数据进行分组
                // 时间分组间隔：DateHistogramInterval.* 序列常量，支持每月，每年，每天等等时间间隔
                .calendarInterval(DateHistogramInterval.MONTH)
                // 设置返回结果中桶key的时间格式
                .format("yyyy-MM-dd");
//                .format("yyyy");

        // 对比上面的（颜色）分组TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_by_color").field("publishDate");
        searchSourceBuilder.aggregation(dateHistogramAggregationBuilder);

        //请求体放入请求头
        searchRequest.source(searchSourceBuilder);

        //2 执行
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        // 处理聚合查询结果
        Aggregations aggregations = searchResponse.getAggregations();
        // 根据sales_over_time命名查询Histogram聚合结果
        Histogram histogram = aggregations.get("sales_over_time");

        // 遍历聚合结果

        List<? extends Histogram.Bucket> buckets = histogram.getBuckets();
        for (Histogram.Bucket bucket : buckets) {
            String key = bucket.getKeyAsString();
            System.out.println("key:" + key);

            long docCount = bucket.getDocCount();
            System.out.println("docCount:" + docCount);

            System.out.println("=================================");
        }
    }

    @Test
    public void testAggs3() throws Exception {
        //range聚合命名为: price_ranges
        //1.
        RangeAggregationBuilder rangeAggregationBuilder = AggregationBuilders.range("price_ranges")
                .field("visits") // 根据price字段分桶
                .addUnboundedFrom(100) // 范围配置, 0 - 100
                .addRange(100.0, 200.0) // 范围配置, 100 - 200
                .addUnboundedTo(200.0); // 范围配置，> 200的值


        //2.搜索
        //构建请求
        SearchRequest searchRequest = new SearchRequest();
        //请求体
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        // 对比上面的（颜色）分组TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_by_color").field("publishDate");
        searchSourceBuilder.aggregation(rangeAggregationBuilder);
        //请求体放入请求头
        searchRequest.source(searchSourceBuilder);
        //执行
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);


        //3. 处理聚合查询结果
        Aggregations aggregations = searchResponse.getAggregations();
        Range range = aggregations.get("price_ranges");

        // 遍历聚合结果
        for (Range.Bucket bucket : range.getBuckets()) {
            // 获取桶的Key值
            String key = bucket.getKeyAsString();
            System.out.println("key:" + key);
            // 获取文档总数
            long count = bucket.getDocCount();
            System.out.println("count:" + count);
        }
    }

    @Test
    public void testAggs4() throws Exception {
        // 创建Terms指标聚合
        TermsAggregationBuilder byShop = AggregationBuilders.terms("by_shop")
                .field("shop_id");

        // 创建avg指标聚合
        AvgAggregationBuilder avgPriceBuilder = AggregationBuilders.avg("avg_price")
                .field("price");
        // 设置嵌套聚合查询条件
        byShop.subAggregation(avgPriceBuilder);

        SumAggregationBuilder sumPriceBulder = AggregationBuilders.sum("sum_price")
                .field("price");
        // 设置嵌套聚合查询条件
        byShop.subAggregation(sumPriceBulder);


        //2.搜索
        //构建请求
        SearchRequest searchRequest = new SearchRequest();
        //请求体
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        // 对比上面的（颜色）分组TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_by_color").field("publishDate");
//        searchSourceBuilder.aggregation(termsAggregationBuilder);
//        searchSourceBuilder.aggregation();todo  此处还未实现
        //请求体放入请求头
        searchRequest.source(searchSourceBuilder);
        //执行
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);


        //3 处理聚合查询结果
        Aggregations aggregations = searchResponse.getAggregations();
        Terms terms = aggregations.get("by_shop");

        // 遍历聚合结果
        for (Terms.Bucket bucket : terms.getBuckets()) {
            // 获取桶的Key值
            String key = bucket.getKeyAsString();
            // 获取文档总数
            long count = bucket.getDocCount();

            // 处理嵌套聚合结果
            Aggregations subAggregations = bucket.getAggregations();
            // 根据avg_price命名，查询avg聚合结果
            Avg avgPriceResult = subAggregations.get("avg_price");
            // 获取平均价格
            double avgPrice = avgPriceResult.getValue();

            // 根据sum_price命名，查询sum聚合结果
            Sum sumPriceResult = subAggregations.get("sum_price");
            // 获取总价格
            double sumPrice = sumPriceResult.getValue();
        }

    }


    /**
     * geo添加坐标点
     */
    @Test
    public void createGEOPoint() throws IOException {
        //创建对象
        User user = new User();
        user.setPlace("棂星门");
        user.setUserId(2001l);
        user.setUserName("Jason Statham");
        GEO geo = new GEO();
        geo.setLon(118.79578);
        geo.setLat(32.026506);

        user.setGeo(geo);

        //创建请求
        IndexRequest request = new IndexRequest("test");
        //规则   put /kuang_index/_doc/1
        request.id("1");//不设置自动
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //  我们的数据放入请求json将
        request.source(JSON.toJSONString(user), XContentType.JSON);
//        客户端发送请求,获取响应的结果
        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());//返回这行记录（doc）
        System.out.println(indexResponse.status());

    }

    /**
     * 地图geo搜索
     * 根据location坐标字段和当前位置，搜索1千米范围的数据
     */

    @Test
    public void geoTest() throws IOException {

        GeoDistanceQueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("geo")
//                .distance("1km") //设置搜索距离为1千米
                .distance(9, DistanceUnit.KILOMETERS)
// 设置当前位置
                .point(new GeoPoint(40.0171214752916, 116.39351697849565));

// 创建SearchRequest对象
        SearchRequest searchRequest = new SearchRequest("test");

// 通过SearchSourceBuilder构建搜索参数
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

// 设置前面创建的ES查询条件
        searchSourceBuilder.query(queryBuilder);

// 构建GeoDistanceSortBuilder设置按距离排序参数（注意此处的GeoPoint为es包下不是lenuce下的）
        GeoDistanceSortBuilder geoDistanceSortBuilder = SortBuilders.geoDistanceSort("geo", new GeoPoint(40.0171214752916, 116.39351697849565));

        //按距离排序 升序排序

        geoDistanceSortBuilder.order(SortOrder.ASC);
        // 设置排序参数
        searchSourceBuilder.sort(geoDistanceSortBuilder);

// 设置搜索请求参数
        searchRequest.source(searchSourceBuilder);
// 执行ES请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.print(searchResponse);

        // 7.解析输出结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println("结果： " + sourceAsString);
        }
        ;
    }

    /**
     * 矩阵搜索
     * 根据location坐标字段和一个矩形范围，匹配文档
     */

    @Test
    public void geoTest2() throws IOException {
        GeoBoundingBoxQueryBuilder queryBuilder = QueryBuilders.geoBoundingBoxQuery("geo")
                .setCorners( // 设置矩形坐标
                        new org.elasticsearch.common.geo.GeoPoint(40.04917820795009, 115.95959861307438), // 设置矩形的左上角坐标
                        new org.elasticsearch.common.geo.GeoPoint(39.848402544660985, 116.54755519845526) // 设置矩形的右下角坐标
                );
/*
        创建SearchRequest
        Java 所有的ES查询请求都是通过SearchRequest对象进行设置，因此需要实例化SearchRequest对象，设置query参数。*/
        SearchRequest searchRequest = new SearchRequest();

// 通过SearchSourceBuilder构建搜索参数

        SearchSourceBuilder builder = new SearchSourceBuilder();

// 设置query参数，绑定前面创建的Query对象

        builder.query(queryBuilder);

// 设置SearchRequest搜索参数
        searchRequest.source(builder);
// 执行ES请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//        System.out.print(searchResponse);

        // 7.解析输出结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println("结果： " + sourceAsString);
        }
    }

    /**
     * Java 映射
     *
     * @throws IOException
     */
    @Test
    public void mappingTest() throws IOException, InterruptedException {
        // 判断index 是否存在
        GetIndexRequest getIndexRequest = new GetIndexRequest("testq");
        boolean exit = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println("是否存在索引::::::" + exit);

        CreateIndexRequest createIndexRequest = new CreateIndexRequest("testq");

        //设置参数 分片和副本
        createIndexRequest.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));

        //指定映射
        Map<String, Object> userId = new HashMap<>();
        userId.put("type", "long");

        Map<String, Object> userName = new HashMap<>();
        userName.put("type", "text");
        userName.put("analyzer", "ik_max_word");
        userName.put("search_analyzer", "ik_smart");

        /**
         * 查准率VS查全率
         * 构建用 ik_max_word，搜索用 ik_smart，所搜时也可以指定分词器忽略指定的搜索分词器
         * 以空格为分割分词可以指定 whitespace 分词器
         * 无法召回 解决方案 1.查询也用也用 ik_max_word 2.更新词库  3.单独新增一个字段 指定用 standard
         */
        Map<String, Object> tag = new HashMap<>();
        tag.put("type", "keyword");


        Map<String, Object> geo = new HashMap<>();
        geo.put("type", "geo_point");

        Map<String, Object> place = new HashMap<>();
        place.put("type", "text");
//        place.put("analyzer", "whitespace");
//        place.put("search_analyzer", "ik_smart");

        Map<String, Object> properties = new HashMap<>();
        properties.put("userId", userId);
        properties.put("userName", userName);
        properties.put("tag", tag);
        properties.put("geo", geo);
        properties.put("place", place);

        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);
/**
 * 一、创建索引，同时指定maping
 *
 */
        /**
         * 01 provided as a Map
         */
//        createIndexRequest.mapping(mapping);
        /**
         * 02 povided as a String
         */
//        createIndexRequest.mapping(
//                        "{\n" +
//                                "  \"properties\": {\n" +
//                                "    \"message\": {\n" +
//                                "      \"type\": \"text\"\n" +
//                                "    }\n" +
//                                "  }\n" +
//                                "}",
//                XContentType.JSON);//还可以指定yml
        /**
         * 03 provided as an XContentBuilder object
         */
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.startObject("properties");
            {
                builder.startObject("message");
                {
                    builder.field("type", "text");
                    builder.field("analyzer", "ik_max_word");
                    builder.field("search_analyzer", "ik_smart");
                }
                builder.endObject();
            }
            builder.endObject();
        }
        builder.endObject();
        createIndexRequest.mapping(builder);
        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);

        System.out.println("创建索引，同时指定maping" + createIndexResponse);

        /**"========================================先创建索引，后  maping================================================="**/
/**
 * 二 【先创建索引】，后  maping
 * 官网 https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.15/java-rest-high-put-mapping.html
 */
        this.createIndex1();
        PutMappingRequest putMappingRequest = new PutMappingRequest("test");

        /**
         * 01 Mapping source provided as a Map which gets automatically converted to JSON forma
         */
        putMappingRequest.source(mapping);

        /**
         *  02Mapping source provided as a String
         */
//        putMappingRequest.source(
//                "{\n" +
//                        "  \"properties\": {\n" +
//                        "    \"message\": {\n" +
//                        "      \"type\": \"text\"\n" +
//                        "    }\n" +
//                        "  }\n" +
//                        "}",
//                XContentType.JSON);
        /**
         * 03.Mapping source provided as an XContentBuilder object, the Elasticsearch built-in helpers to generate JSON content
         */
//        XContentBuilder builder = XContentFactory.jsonBuilder();
//        builder.startObject();
//        {
//            builder.startObject("properties");
//            {
//                builder.startObject("message");
//                {
//                    builder.field("type", "text");
//                }
//                builder.endObject();
//            }
//            builder.endObject();
//        }
//        builder.endObject();
//        putMappingRequest.source(builder);
        //其他
//        putMappingRequest.setTimeout(TimeValue.timeValueMinutes(2));
//        putMappingRequest.setMasterTimeout(TimeValue.timeValueMinutes(1));
        /**
         * 01同步 客户端将等待返回PutMappingResponse，然后继续执行代码：
         */
       /* AcknowledgedResponse putMappingResponse = client.indices().putMapping(putMappingRequest, RequestOptions.DEFAULT);
        boolean acknowledged = putMappingResponse.isAcknowledged();
        System.out.println("同步创建返回"+acknowledged);*/

        /**
         *  02asynchronous 还可以以异步方式执行PutMappingRequest，以便客户端可以直接返回。
         *  用户需要通过将请求和侦听器传递给异步put映射方法来指定如何处理响应或潜在故障
         *  https://blog.csdn.net/hunheidaode/article/details/109373520 同步异步的 关闭索引同步异步 打开索引同步异步  关闭时不能添加文档
         */

     /*   client.indices().putMappingAsync(putMappingRequest, RequestOptions.DEFAULT, listener);
        Thread.sleep(5000);*/

        //03 elasticsearchRestTemplate 实体类注解直接指定 mapping 注意没有ik分词器时，指定分词注解也会导致mapping失败
        boolean index = elasticsearchRestTemplate.createIndex(People.class);
        elasticsearchRestTemplate.putMapping(People.class);

    }
    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
        @Test
    public void  createMapingByAnnotation(){
        boolean index = elasticsearchRestTemplate.createIndex(ChatRecordBusinessData.class);
        elasticsearchRestTemplate.putMapping(ChatRecordBusinessData.class);
    }

//异步删除索引  参考官网可异步查询
    @Test
    public void delete1() throws IOException, InterruptedException {
        DeleteIndexRequest deleteIndexRequest1 = new DeleteIndexRequest("test");
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("testq");
//        deleteIndexRequest.timeout(TimeValue.timeValueMinutes(2));

        ActionListener<AcknowledgedResponse> actionListener = new ActionListener<AcknowledgedResponse>() {
            @Override
            public void onResponse(AcknowledgedResponse acknowledgedResponse) {
                System.out.println("异步删除索引！！！！！！！");
                System.out.println("isAcknowledged:" + acknowledgedResponse.isAcknowledged());
                System.out.println("acknowledgedResponse:" + acknowledgedResponse.isFragment());
            }

            @Override
            public void onFailure(Exception e) {
                e.printStackTrace();
                System.out.println("删除失败！！！！！");
            }
        };

        client.indices().deleteAsync(deleteIndexRequest, RequestOptions.DEFAULT, actionListener);

        AcknowledgedResponse acknowledgedResponse = client.indices().delete(deleteIndexRequest1, RequestOptions.DEFAULT);
        System.out.println("同步删除索引！！！！！！！");
        System.out.println("isAcknowledged:" + acknowledgedResponse.isAcknowledged());
        System.out.println("acknowledgedResponse:" + acknowledgedResponse.isFragment());
        //这里必须加一个线程睡眠，test方法停止就没你啥事了，不像服务
        Thread.sleep(5000);


    }

    @Test
    public void createIndex1() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("test");
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }
 /*   @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Test
    public void searcIk(){
        AnalyzeRequestBuilder ikRequest = new AnalyzeRequestBuilder(elasticsearchTemplate.getClient(), AnalyzeAction.INSTANCE);
        ikRequest.setTokenizer("ik");
        List<AnalyzeAction.AnalyzeToken> ikTokenList = ikRequest.execute().actionGet().getTokens();
//        List<AnalyzeResponse.AnalyzeToken> ikTokenList = ikRequest.execute().actionGet().getTokens();

        // 循环赋值
        List<String> searchTermList = new ArrayList<>();
        ikTokenList.forEach(ikToken -> { searchTermList.add(ikToken.getTerm()); });

        System.out.println(searchTermList); ;
    }*/

    @Test
    public void caicaiCreateDoc() throws IOException {
        //创建对象
        Map<String, Object> map = new HashMap<>();

        map.put("userId", new Long(123));
        map.put("userName", "张山");
        map.put("tag", "小王");
//        map.put("geo", geo);
        map.put("place", "杭州市西湖区西溪路cscascascac");
        //创建请求
        IndexRequest request = new IndexRequest("test");
//        request.id("1");//不设置自动
        request.timeout(TimeValue.timeValueSeconds(1));
        request.timeout("1s");
        //  我们的数据放入请求json将
        request.source(JSON.toJSONString(map), XContentType.JSON);
//        客户端发送请求,获取响应的结果

        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        System.out.println(indexResponse.toString());//返回这行记录（doc）
        System.out.println(indexResponse.status());
        ;//对应我们命令返回的状态CREATED

    }


    @Test
    public void caicaiSearch() throws IOException {
        //1.searchRequest 索引名不加为全文搜索
        SearchRequest searchRequest = new SearchRequest("test");


        //2、构建搜索条件；我们可以使用QueryBuiLders工具来实现（
        // QueryBuilders.termQuery()精确
        //QueryBuilders.matchAllQuery()//匹配所有）

        //1.1 根据时间范围查询
//        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishDate").from("2017-11-01").to("2017-11-31", true);

//        QueryBuilder matchQueryqueryBuilder = matchQuery("tag", "王");
        QueryBuilder matchQueryqueryBuilder = matchQuery("userName", "张山ww张山");
//        todo  MatchPhraseQueryBuilder 比matchQueryqueryBuilder人性化
        MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders
                .matchPhraseQuery("userName", "张山ww张山");


        // 2.构建SearchRequest请求对象,指定索引库

        //1.2高亮查询
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("keyword");
        highlightBuilder.preTags("<span style='color:blue;font-weight: 900'>");
        highlightBuilder.postTags("</span>");

        //1.3精确查询
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("tag", "小王王");

        //1.4全匹配
        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();

        String text = "这是一个号的现象么!";
//        AnalyzeRequest an = new AnalyzeRequest( "test",  "ik_smart",  "normalizer",  "tag","小王王");
        //3
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        sourceBuilder.size(100);//默认查10
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//      sourceBuilder.from() //默认-1

        sourceBuilder.query(termQueryBuilder);
        sourceBuilder.query(matchQueryqueryBuilder);
//        sourceBuilder.query(matchPhraseQueryBuilder);
//        sourceBuilder.query(rangeQueryBuilder);
//      sourceBuilder.query(QueryBuilders.matchAllQuery());
//      sourceBuilder.highlighter(highlightBuilder);

        // *******将SearchSourceBuilder查询对象封装到请求对象SearchRequest中,否则全匹配  sourceBuilder没起作用啊
        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(searchResponse);
        System.out.println(JSON.toJSONString(searchResponse.getHits().getTotalHits()));
        System.out.println("===================================");

        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
            System.out.println(documentFields.getSourceAsMap());
        }

        for (SearchHit hit : searchResponse.getHits()) {
            String id = hit.getId();
            String sourceAsString = hit.getSourceAsString();
            System.out.println("结果：" + JSON.parseObject(sourceAsString));
//            System.out.println("结果：" + JSON.parseObject(sourceAsString).get("publishDate"));
//            System.out.println("结果id：" + id);
        }
    }

    /**
     * 多条件查询
     *
     * @throws IOException
     */
    @Test
    public void BoolSearch() throws IOException {

        SearchRequest searchRequest = new SearchRequest("case_info_b");

        /**
         *
         * must:   AND
         * mustNot: NOT
         * should:: OR
         */

        //前缀查询【多条件设置】
        MatchPhraseQueryBuilder mpq1 = QueryBuilders
                .matchPhraseQuery("typeName", "公证业务案例");

        MatchPhraseQueryBuilder mpq2 = QueryBuilders
                .matchPhraseQuery("approveDate", "2021-11-14");

        BoolQueryBuilder bq1 = QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("distName", "徐汇区"))
                .must(QueryBuilders.termQuery("uploadDeptName", "虹口区司法局"));

//        【BoolQueryBuilder queryBuilder】
        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(mpq1)
                //直接构建一个条件精确查询
                .must(QueryBuilders.termQuery("updateTime", "2021-11-15"))
                //must里嵌套一个多条件查询 看你怎么完  and  or
//                .must(QueryBuilders.boolQuery()
//                        .should(QueryBuilders.termQuery("distName","徐汇区"))
//                        .must(QueryBuilders.termQuery("uploadDeptName", "虹口区司法局")))
//                .must(bq1)
                .must(mpq2);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        sourceBuilder.query(queryBuilder);

//        sourceBuilder.size(10).from(0).sort("").explain(true);
//        sourceBuilder.size(100);//默认查10
//        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
////      sourceBuilder.from() //默认-1


        searchRequest.source(sourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("searchResponse::::::::" + searchResponse);

        SearchHits hits = searchResponse.getHits();
        for (int i = 0; i < hits.getHits().length; i++) {
            System.out.println(hits.getHits()[i].getSourceAsString());

        }
    }
    /**



    /**
     * 指定案例库maping
     *
     * @throws IOException
     */
    @Test
    public void maping_case1() throws IOException {
        // 判断index 是否存在
        GetIndexRequest getIndexRequest = new GetIndexRequest("case_info_b");
        boolean exit = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(exit + "-----------------");
        CreateIndexRequest createIndexRequest = null;
        if (!exit) {
            createIndexRequest = new CreateIndexRequest("case_info_b");
        }

        //设置参数 分片和副本
//        createIndexRequest.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));
        Map<String, Object> properties = new HashMap<>();


        //指定映射

        Map<String, Object> approveDate = new HashMap<>();
        approveDate.put("type", "date");
        properties.put("approveDate", approveDate);

        Map<String, Object> columnId = new HashMap<>();
        columnId.put("type", "keyword");
        properties.put("columnId", columnId);

        Map<String, Object> publishHair = new HashMap<>();
        publishHair.put("type", "keyword");
        properties.put("publishHair", publishHair);

        Map<String, Object> isLegality = new HashMap<>();
        isLegality.put("type", "long");
        properties.put("isLegality", isLegality);

        Map<String, Object> publishDate = new HashMap<>();
        publishDate.put("type", "date");
        properties.put("publishDate", publishDate);

        Map<String, Object> source = new HashMap<>();
        source.put("type", "text");
        properties.put("source", source);

        Map<String, Object> isActive = new HashMap<>();
        isActive.put("type", "long");
        properties.put("isActive", isActive);

        Map<String, Object> approveStart = new HashMap<>();
        approveStart.put("type", "keyword");
        properties.put("approveStart", approveStart);


        Map<String, Object> tagInfo = new HashMap<>();
        tagInfo.put("type", "keyword");
        properties.put("tagInfo", tagInfo);


        Map<String, Object> distCode = new HashMap<>();
        distCode.put("type", "keyword");
        properties.put("distCode", distCode);


        Map<String, Object> sybiosis = new HashMap<>();
        sybiosis.put("type", "text");
        properties.put("sybiosis", sybiosis);


        Map<String, Object> uploadDeptId = new HashMap<>();
        uploadDeptId.put("type", "keyword");
        properties.put("uploadDeptId", uploadDeptId);


        Map<String, Object> clickRate = new HashMap<>();
        clickRate.put("type", "long");
        properties.put("clickRate", clickRate);

        Map<String, Object> caseId = new HashMap<>();
        caseId.put("type", "keyword");
        properties.put("caseId", caseId);


        Map<String, Object> context = new HashMap<>();
        context.put("type", "text");
        properties.put("context", context);


        Map<String, Object> keyword = new HashMap<>();
        keyword.put("type", "text");
        properties.put("keyword", keyword);


        Map<String, Object> approver = new HashMap<>();
        approver.put("type", "text");
        properties.put("approver", approver);


        Map<String, Object> creator = new HashMap<>();
        creator.put("type", "keyword");
        properties.put("creator", creator);


        Map<String, Object> author = new HashMap<>();
        author.put("type", "text");
        properties.put("author", author);


        Map<String, Object> caseTitle = new HashMap<>();
        caseTitle.put("type", "text");
        properties.put("caseTitle", caseTitle);


        Map<String, Object> textType = new HashMap<>();
        textType.put("type", "keyword");
        properties.put("textType", textType);


        Map<String, Object> updateTime = new HashMap<>();
        updateTime.put("type", "date");
        properties.put("updateTime", updateTime);


        Map<String, Object> isPublish = new HashMap<>();
        isPublish.put("type", "long");
        properties.put("isPublish", isPublish);


        Map<String, Object> isTopping = new HashMap<>();
        isTopping.put("type", "text");
        properties.put("isTopping", isTopping);


        Map<String, Object> uploadDate = new HashMap<>();
        uploadDate.put("type", "date");
        properties.put("uploadDate", uploadDate);


        Map<String, Object> createTime = new HashMap<>();
        createTime.put("type", "date");
        properties.put("createTime", createTime);

        Map<String, Object> uploadDeptName = new HashMap<>();
        uploadDeptName.put("type", "keyword");
        properties.put("uploadDeptName", uploadDeptName);

        Map<String, Object> updator = new HashMap<>();
        updator.put("type", "text");
        properties.put("updator", updator);


        Map<String, Object> distName = new HashMap<>();
        distName.put("type", "keyword");
        properties.put("distName", distName);

        Map<String, Object> typeId = new HashMap<>();
        typeId.put("type", "keyword");
        properties.put("typeId", typeId);


        Map<String, Object> typeName = new HashMap<>();
        typeName.put("type", "keyword");
        properties.put("typeName", typeName);

        Map<String, Object> isPopularizeLaw = new HashMap<>();
        isPopularizeLaw.put("type", "text");
        properties.put("isPopularizeLaw", isPopularizeLaw);


        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);
        createIndexRequest.mapping(mapping);

        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
//        先创建索引，单独指定maping
       /* PutMappingRequest putMappingRequest=new PutMappingRequest(JSON.toJSONString(new User()), XContentType.JSON);
        AcknowledgedResponse acknowledgedResponse = client.indices().putMapping(putMappingRequest);*/

        System.out.println(createIndexResponse);

    }

    /**
     * 指定法网maping
     *
     * @throws IOException
     */

    @Test
    public void maping_law1() throws IOException {
        // 判断index 是否存在
        GetIndexRequest getIndexRequest = new GetIndexRequest("law_info_b");
        boolean exit = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(exit + "-----------------");
        CreateIndexRequest createIndexRequest = null;
        if (!exit) {
            createIndexRequest = new CreateIndexRequest("law_info_b");
        }

        //设置参数 分片和副本
//        createIndexRequest.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));
        Map<String, Object> properties = new HashMap<>();


        //指定映射

        Map<String, Object> columnId = new HashMap<>();
        columnId.put("type", "keyword");
        properties.put("columnId", columnId);


        Map<String, Object> publishHair = new HashMap<>();
        publishHair.put("type", "keyword");
        properties.put("publishHair", publishHair);

        Map<String, Object> publishDate = new HashMap<>();
        publishDate.put("type", "date");
        properties.put("publishDate", publishDate);

        Map<String, Object> auditIdea = new HashMap<>();
        auditIdea.put("type", "text");
        properties.put("auditIdea", auditIdea);


        Map<String, Object> source = new HashMap<>();
        source.put("type", "text");
        properties.put("source", source);


        Map<String, Object> isActive = new HashMap<>();
        isActive.put("type", "long");
        properties.put("isActive", isActive);

        Map<String, Object> tagInfo = new HashMap<>();
        tagInfo.put("type", "keyword");
        properties.put("tagInfo", tagInfo);


        Map<String, Object> distCode = new HashMap<>();
        distCode.put("type", "keyword");
        properties.put("distCode", distCode);


        Map<String, Object> sybiosis = new HashMap<>();
        sybiosis.put("type", "text");
        properties.put("sybiosis", sybiosis);


        Map<String, Object> uploadDeptId = new HashMap<>();
        uploadDeptId.put("type", "keyword");
        properties.put("uploadDeptId", uploadDeptId);


        Map<String, Object> clickRate = new HashMap<>();
        clickRate.put("type", "long");
        properties.put("clickRate", clickRate);

        Map<String, Object> context = new HashMap<>();
        context.put("type", "text");
        properties.put("context", context);

        Map<String, Object> contextTitle = new HashMap<>();
        contextTitle.put("type", "text");
        properties.put("caseId", contextTitle);


        Map<String, Object> auditDate = new HashMap<>();
        auditDate.put("type", "date");
        properties.put("keyword", auditDate);

        Map<String, Object> creator = new HashMap<>();
        creator.put("type", "keyword");
        properties.put("creator", creator);

        Map<String, Object> contextSubtitle = new HashMap<>();
        contextSubtitle.put("type", "text");
        properties.put("caseTitle", contextSubtitle);

        Map<String, Object> author = new HashMap<>();
        author.put("type", "text");
        properties.put("author", author);


        Map<String, Object> auditor = new HashMap<>();
        auditor.put("type", "text");
        properties.put("auditor", auditor);


        Map<String, Object> contextId = new HashMap<>();
        contextId.put("type", "keyword");
        properties.put("textType", contextId);

        Map<String, Object> updateTime = new HashMap<>();
        updateTime.put("type", "date");
        properties.put("updateTime", updateTime);


        Map<String, Object> isPublish = new HashMap<>();
        isPublish.put("type", "long");
        properties.put("isPublish", isPublish);


        Map<String, Object> isTopping = new HashMap<>();
        isTopping.put("type", "text");
        properties.put("isTopping", isTopping);


        Map<String, Object> createTime = new HashMap<>();
        createTime.put("type", "date");
        properties.put("createTime", createTime);


        Map<String, Object> uploadDeptName = new HashMap<>();
        uploadDeptName.put("type", "keyword");
        properties.put("uploadDeptName", uploadDeptName);

        Map<String, Object> updator = new HashMap<>();
        updator.put("type", "keyword");
        properties.put("updator", updator);


        Map<String, Object> distName = new HashMap<>();
        distName.put("type", "keyword");
        properties.put("distName", distName);


        Map<String, Object> auditStart = new HashMap<>();
        auditStart.put("type", "keyword");
        properties.put("auditStart", auditStart);


        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);
        createIndexRequest.mapping(mapping);

        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
//        先创建索引，单独指定maping
       /* PutMappingRequest putMappingRequest=new PutMappingRequest(JSON.toJSONString(new User()), XContentType.JSON);
        AcknowledgedResponse acknowledgedResponse = client.indices().putMapping(putMappingRequest);*/

        System.out.println(createIndexResponse);

    }


    /**
     * 智障问答maping
     *
     * @throws IOException
     */

    @Test
    public void maping_IntelligentQA() throws IOException {
        // 判断index 是否存在
        GetIndexRequest getIndexRequest = new GetIndexRequest("intelligent_qa");
        boolean exit = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(exit + "-----------------");
        CreateIndexRequest createIndexRequest = null;
        if (!exit) {
            createIndexRequest = new CreateIndexRequest("intelligent_qa");
        }

        //设置参数 分片和副本
//        createIndexRequest.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));
        Map<String, Object> properties = new HashMap<>();


        //指定映射

        Map<String, Object> id = new HashMap<>();
        id.put("type", "keyword");
        properties.put("id", id);


        Map<String, Object> title = new HashMap<>();
        title.put("type", "text");
        properties.put("title", title);


        Map<String, Object> publicDate = new HashMap<>();
        publicDate.put("type", "date");
        properties.put("publicDate", publicDate);

        Map<String, Object> carryDate = new HashMap<>();
        carryDate.put("type", "date");
        properties.put("carryDate", carryDate);


        Map<String, Object> keyword = new HashMap<>();
        keyword.put("type", "keyword");
        properties.put("keyword", keyword);


        Map<String, Object> department = new HashMap<>();
        department.put("type", "text");
        properties.put("department", department);

        Map<String, Object> publicContent = new HashMap<>();
        publicContent.put("type", "text");
        properties.put("publicContent", publicContent);

        Map<String, Object> isEffective = new HashMap<>();
        isEffective.put("type", "keyword");
        properties.put("isEffective", isEffective);


        Map<String, Object> type = new HashMap<>();
        type.put("type", "keyword");
        properties.put("type", type);


        Map<String, Object> lawType = new HashMap<>();
        lawType.put("type", "keyword");
        properties.put("lawType", lawType);


        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);
        createIndexRequest.mapping(mapping);

        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
//        先创建索引，单独指定maping
       /* PutMappingRequest putMappingRequest=new PutMappingRequest(JSON.toJSONString(new User()), XContentType.JSON);
        AcknowledgedResponse acknowledgedResponse = client.indices().putMapping(putMappingRequest);*/

        System.out.println(createIndexResponse);

    }

    /**
     * 智障问答 问题mapping
     */
    @Test
    public void maping_IntelligentQA2() throws IOException {

        // 判断index 是否存在
        GetIndexRequest getIndexRequest = new GetIndexRequest("intelligent_answers");
        boolean exit = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(exit + "-----------------");
        CreateIndexRequest createIndexRequest = null;
        if (!exit) {
            createIndexRequest = new CreateIndexRequest("intelligent_answers");
        }

        //设置参数 分片和副本
//        createIndexRequest.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));
        Map<String, Object> properties = new HashMap<>();


        //指定映射

        Map<String, Object> id = new HashMap<>();
        id.put("type", "keyword");
        properties.put("id", id);


        Map<String, Object> title = new HashMap<>();
        title.put("type", "text");
        properties.put("title", title);


        Map<String, Object> qContent = new HashMap<>();
        qContent.put("type", "text");
        properties.put("qContent", qContent);


        Map<String, Object> isAnswer = new HashMap<>();
        isAnswer.put("type", "text");
        properties.put("isAnswer", isAnswer);

        Map<String, Object> userName = new HashMap<>();
        userName.put("type", "text");
        properties.put("userName", userName);

        Map<String, Object> userId = new HashMap<>();
        userId.put("type", "keyword");
        properties.put("userId", userId);

        Map<String, Object> commitTime = new HashMap<>();
        commitTime.put("type", "date");
        properties.put("commitTime", commitTime);

        Map<String, Object> isOpen = new HashMap<>();
        isOpen.put("type", "text");
        properties.put("isOpen", isOpen);

        Map<String, Object> userType = new HashMap<>();
        userType.put("type", "text");
        properties.put("userType", userType);

        Map<String, Object> userAddr = new HashMap<>();
        userAddr.put("type", "text");
        properties.put("userAddr", userAddr);

        Map<String, Object> qType = new HashMap<>();
        qType.put("type", "text");
        properties.put("qType", qType);


        Map<String, Object> businessType = new HashMap<>();
        businessType.put("type", "text");
        properties.put("businessType", businessType);


        Map<String, Object> consultType = new HashMap<>();
        consultType.put("type", "text");
        properties.put("consultType", consultType);


        Map<String, Object> phone = new HashMap<>();
        phone.put("type", "text");
        properties.put("phone", phone);

        Map<String, Object> userAddrName = new HashMap<>();
        userAddrName.put("type", "text");
        properties.put("userAddrName", userAddrName);

        Map<String, Object> caseAnswerBean = new HashMap<>();
        caseAnswerBean.put("type", "text");
        properties.put("caseAnswerBean", caseAnswerBean);

        Map<String, Object> answerString = new HashMap<>();
        answerString.put("type", "text");
        properties.put("answerString", answerString);

        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);
        createIndexRequest.mapping(mapping);

        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
//        先创建索引，单独指定maping
       /* PutMappingRequest putMappingRequest=new PutMappingRequest(JSON.toJSONString(new User()), XContentType.JSON);
        AcknowledgedResponse acknowledgedResponse = client.indices().putMapping(putMappingRequest);*/

        System.out.println(createIndexResponse);


    }
}


